home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / ingres04.lzh / source / decomp / byeval.c < prev    next >
Encoding:
C/C++ Source or Header  |  1985-12-18  |  8.2 KB  |  327 lines

  1. # include    <ingres.h>
  2. # include    <tree.h>
  3. # include    <symbol.h>
  4. # include    <pv.h>
  5. # include    "globs.h"
  6. # include    <sccs.h>
  7. # include    <errors.h>
  8.  
  9. SCCSID(@(#)byeval.c    8.3    12/18/85)
  10.  
  11. /*
  12. **    BYEVAL - process aggregate function
  13. **
  14. **    Byeval is passed the root of the original query
  15. **    tree and the root of the aggregate function to
  16. **    be processed.
  17. **
  18. **    It first creates a temporary relation which will
  19. **    hold the aggregate result. The format of the relation
  20. **    is:
  21. **    _SYSxxxxxaa(count, by-dom1, ... , by-domn, ag1, ... , agm)
  22. **
  23. **    The relation is moved into the range table and will become
  24. **    a part of the query.
  25. **
  26. **    If there are any occurences of the variables
  27. **    from the by-domains, anywhere in the original query tree,
  28. **    the aggregate relation is linked on all by-domains in the
  29. **    original query tree.
  30. **
  31. **    If the aggregate is unique, multivariable, or has a
  32. **    qualification, then special processing is done.
  33. **
  34. **    If the aggregate is qualified then the by-domains are
  35. **    projected into the result relation. This guarantees that
  36. **    every value of the by-domains will be represented in the
  37. **    aggregate result.
  38. **
  39. **    If the aggregate is unique or multivariable, then another
  40. **    temporary relation is created and the values which will be
  41. **    aggregated; along with the by-domains, are retrieved into
  42. **    the temporary relation.
  43. **
  44. **    If unique, then duplicates are removed from the temporary relation.
  45. **
  46. **    Next the result relation for the aggregate is modified
  47. **    to hash in order to speed up the processing of the aggregate
  48. **    and guarantee that there are no duplicates in the bylist.
  49. **
  50. **    The aggregate is then run, and if a temporary relation was
  51. **    created (eg. unique or multivar aggregate) then it is destroyed.
  52. **
  53. **    Trace Flags:
  54. **        42
  55. */
  56.  
  57.  
  58. QTREE *
  59. byeval(root, aghead, agvar)
  60. QTREE    *root;        /* root of orig query */
  61. QTREE    *aghead;    /* root of ag fcn sub-tree */
  62. int    agvar;        /* variable number assigned to this aggregate */
  63. {
  64.  
  65.     register QTREE     *q, *ag, *resdom;
  66.     QTREE        *r;
  67.     int        temp_relnum, i, filled;
  68.     QTREE        *lnodv[MAXDOM+2], *save_node[MAXDOM+2];
  69.     int        agbuf[1+AGBUFSIZ/sizeof(int)];
  70.     char        nums[2];
  71.     int        relnum;
  72.     QTREE         *byhead, **alnp;
  73.     int        bydoms, bymap, primeag, srcmap;
  74.     extern int    derror();
  75.     extern QTREE    *makroot(), *makavar(), *makresdom(), *copytree();
  76.     extern char    *rnum_convert();
  77.  
  78. #    ifdef xDTR1
  79.     if (tTf(42, -1))
  80.         printf("BYEVAL\n");
  81. #    endif
  82.  
  83.     ag = aghead;
  84.     byhead = ag->left;
  85.  
  86.     /* first create the aggregate result relation */
  87.     /* params for create */
  88.  
  89.     initp();    /* init globals for setp */
  90.     setp(PV_STR,"0");    /* initial relstat field */
  91.     relnum = rnum_alloc();
  92.     setp(PV_STR,rnum_convert(relnum));
  93.     setp(PV_STR,"count");    /* domain 1 - count field per BY value */
  94.     setp(PV_STR,"i4");    /* format of count field */
  95.  
  96.     i = bydoms = lnode(byhead->left, lnodv, 0);
  97.     lnodv[i] = 0;
  98.     alnp = &lnodv[++i];
  99.     i = lnode(byhead->right, lnodv, i);
  100.     lnodv[i] = 0;
  101.  
  102.     domnam(lnodv, "by");    /* BY list domains */
  103.     domnam(alnp, "ag");    /* aggregate value domains */
  104.  
  105.     call_dbu(mdCREATE, FALSE);
  106.  
  107.     De.de_rangev[agvar].relnum = relnum;
  108. #    ifdef xDTR1
  109.     if (tTf(42, 7))
  110.         printf("agvar=%d,rel=%s\n", agvar, rnum_convert(relnum));
  111. #    endif
  112.  
  113.     bymap = varfind(byhead->left, (QTREE *)NULL);
  114.  
  115.     /*
  116.     ** Find all variables in the tree in which you are nested.
  117.     ** Do not look at any other aggregates in the tree. Just in
  118.     ** case the root is an aggregate, explicitly look at its
  119.     ** two descendents.
  120.     */
  121.     srcmap = varfind(root->left, ag) | varfind(root->right, ag);
  122. #    ifdef xDTR1
  123.     if (tTf(42, 8))
  124.         printf("bymap=%o,srcmap=%o\n", bymap, srcmap);
  125. #    endif
  126.  
  127.     if (bymap & srcmap)
  128.         modqual(root, lnodv, srcmap, agvar);
  129.  
  130.     /* if aggregate is unique or there is a qualification
  131.     ** or aggregate is multi-var, then special processing is done */
  132.  
  133.     temp_relnum = NORESULT;
  134.     filled = FALSE;
  135.     primeag = prime(byhead->right);
  136.     if (ag->right->sym.type != QLEND || ag->sym.value.sym_root.tvarc > 1 || primeag)
  137.     {
  138.         /* init a buffer for new tree components */
  139.         initbuf((char *)agbuf, AGBUFSIZ, AGBUFFULL, derror);
  140.  
  141.         /* make a root for a new tree */
  142.         q = makroot((char *)agbuf);
  143.  
  144.         /*
  145.         ** Create a RESDOM for each by-domain in the original
  146.         ** aggregate. Rather than using the existing by-domain
  147.         ** function, a copy is used instead. This is necessary
  148.         ** since that subtree might be needed later (if modqual())
  149.         ** decided to use it. Decomp does not restore the trees
  150.         ** it uses and thus the by-domains might be altered.
  151.         */
  152.         for (i = 0; r = lnodv[i]; i++)
  153.         {
  154.             resdom = makresdom((char *)agbuf, r);
  155.             resdom->sym.value.sym_resdom.resno = i + 2;
  156.             resdom->right = copytree(r->right, (char *)agbuf);
  157.             resdom->left = q->left;
  158.             q->left = resdom;
  159.         }
  160.         mapvar(q, 0);    /* make maps on root */
  161. #        ifdef xDTR1
  162.         if (tTf(42, 2))
  163.         {
  164.             printf("byedomains\n");
  165.             treepr(q);
  166.         }
  167. #        endif
  168.  
  169.         /* if agg is qualified, project by-domains into result */
  170.         if (ag->right->sym.type != QLEND)
  171.         {
  172.             filled = TRUE;
  173.             i = De.de_sourcevar;    /* save value */
  174.             decomp(q, mdRETR, relnum);
  175.             De.de_sourcevar = i;    /* restore value */
  176.         }
  177.  
  178.         /* if agg is prime or multivar, compute into temp rel */
  179.         if (ag->sym.value.sym_root.tvarc > 1 || primeag)
  180.         {
  181.             q->right = ag->right;    /* give q the qualification */
  182.             ag->right = De.de_qle;    /* remove qualification from ag */
  183.  
  184.             /* put aop resdoms on tree */
  185.             for (i = bydoms + 1; r = lnodv[i]; i++)
  186.             {
  187.                 resdom = makresdom((char *)agbuf, r);
  188.                 resdom->right = r->right;
  189.                 resdom->left = q->left;
  190.                 q->left = resdom;
  191.  
  192.                 /* make aop refer to temp relation */
  193.                 r->right = makavar(resdom, FREEVAR, i);
  194.             }
  195.  
  196.             /* assign result domain numbers */
  197.             for (resdom = q->left; resdom->sym.type != TREE; resdom = resdom->left)
  198.                 resdom->sym.value.sym_resdom.resno = --i;
  199.  
  200.             /*
  201.             ** change by-list in agg to reference new source rel.
  202.             ** Save the old bylist to be restored at the end of
  203.             ** this aggregate.
  204.             */
  205.             for (i = 0; resdom = lnodv[i]; i++)
  206.             {
  207.                 save_node[i] = resdom->right;
  208.                 resdom->right = makavar(resdom, FREEVAR, i + 1);
  209.             }
  210.  
  211.             mapvar(q, 0);
  212. #            ifdef xDTR1
  213.             if (tTf(42, 3))
  214.             {
  215.                 printf("new ag src\n");
  216.                 treepr(q);
  217.             }
  218. #            endif
  219.  
  220.             /* create temp relation */
  221.             temp_relnum = mak_t_rel(q, "a", -1);
  222.             decomp(q, mdRETR, temp_relnum);
  223.             De.de_rangev[FREEVAR].relnum = temp_relnum;
  224.             De.de_sourcevar = FREEVAR;
  225.             if (primeag)
  226.                 removedups(FREEVAR);
  227. #            ifdef xDTR1
  228.             if (tTf(42, 4))
  229.             {
  230.                 printf("new agg\n");
  231.                 treepr(ag);
  232.             }
  233. #            endif
  234.         }
  235.     }
  236.  
  237.     /* set up parameters for modify to hash */
  238.     initp();
  239.     setp(PV_STR, rnum_convert(relnum));
  240.     setp(PV_STR, "hash");    /* modify the empty rel to hash */
  241.     setp(PV_STR, "num");    /* code to indicate numeric domain names */
  242.     nums[1] = '\0';
  243.     for (i = 0; i < bydoms; i++)
  244.     {
  245.         nums[0] = i + 2;
  246.         setp(PV_STR, nums);
  247.     }
  248.     setp(PV_STR, "");
  249.  
  250.     /* set up fill factor information */
  251.     setp(PV_STR,"minpages");
  252.     if (filled)
  253.     {
  254.         setp(PV_STR,"1");
  255.         setp(PV_STR,"fillfactor");
  256.         setp(PV_STR,"100");
  257.     }
  258.     else
  259.     {
  260.         setp(PV_STR,"10");
  261.     }
  262.     specclose(relnum);
  263.     call_dbu(mdMODIFY, FALSE);
  264.  
  265.  
  266.     De.de_newq = 1;
  267.     De.de_newr = TRUE;
  268.     call_ovqp(ag, mdRETR, relnum);
  269.  
  270.     De.de_newq = 0;
  271.     /* if temp relation was used, destroy it */
  272.     if (temp_relnum != NORESULT)
  273.     {
  274.         for (i = 0; resdom = lnodv[i]; i++)
  275.             resdom->right = save_node[i];
  276.         dstr_rel(temp_relnum);
  277.     }
  278. }
  279.  
  280.  
  281.  
  282.  
  283. modqual(root, lnodv, srcmap, agvar)
  284. QTREE    *root;
  285. QTREE    *lnodv[];
  286. int    srcmap;
  287. int    agvar;
  288. {
  289.     register QTREE    *and_eq, *afcn;
  290.     register int    i;
  291.     extern QTREE    *copytree();
  292.     extern char    *need();
  293.     register int    len;
  294.  
  295. #    ifdef xDTR1
  296.     if (tTf(42, 12))
  297.         printf("modqual %o\n", srcmap);
  298. #    endif
  299.  
  300.     for (i = 0; afcn = lnodv[i]; i++)
  301.     {
  302.         /*  `AND' node  */
  303.         len = sizeof (struct rootnode) - sizeof (short);
  304.         and_eq = (QTREE *) need(De.de_qbuf, QT_HDR_SIZ + len);
  305.         and_eq->sym.type = AND;
  306.         and_eq->sym.len = len;
  307.         and_eq->sym.value.sym_root.tvarc = 0;
  308.         and_eq->sym.value.sym_root.lvarc = 0;
  309.         and_eq->sym.value.sym_root.lvarm = 0;
  310.         and_eq->sym.value.sym_root.rvarm = 0;
  311.         and_eq->right = root->right;
  312.         root->right = and_eq;
  313.  
  314.         /* `EQ' node  */
  315.         len = sizeof (struct opnode);
  316.         and_eq->left = (QTREE *) need(De.de_qbuf, QT_HDR_SIZ + len);
  317.         and_eq = and_eq->left;
  318.         and_eq->sym.type = BOP;
  319.         and_eq->sym.len = len;
  320.         and_eq->sym.value.sym_op.opno = opEQ;
  321.  
  322.         /* bydomain opEQ var */
  323.         and_eq->right = copytree(afcn->right, De.de_qbuf);    /* a-fcn (in Source) specifying BY domain */
  324.         and_eq->left = makavar(afcn, agvar, i+2);    /* VAR ref BY domain */
  325.     }
  326. }
  327.